/*
 * Copyright (C) 2009 Ionut Dediu <deionut@yahoo.com>
 *
 * Licensed under the GNU General Public License Version 2
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

// SmartCamAppUi.cpp

#include <avkon.hrh>
#include <aknmessagequerydialog.h>
#include <aknnotewrappers.h>
#include <eikspane.h>		// For CEikStatusPane
#include <aknnavi.h>		// For CAknNavigationControlContainer
#include <aknnavide.h>		// For CAknNavigationDecorator
#include <aknquerydialog.h>	// For CAknQueryDialog, CAknTextQueryDialog

#include <f32file.h>
#include <s32file.h>
#include <hlplch.h>

#include <SmartCam_0xE696FBC9.rsg>
#include <SmartCamGfx.mbg>

#include "SmartCamAppUi.h"

#include "SmartCam.hrh"
#include "SmartCam.pan"
#include "SmartCamApplication.h"
#include "SmartCamViewFinderView.h"
#include "SmartCamSettingsView.h"
#include "SmartCamSettingsData.h"
#include "SmartCamConst.h"
#include "SmartCam_0xE696FBC9.hlp.hrh"

// sordak
#define  ONE_SECOND            1000 * 1000

CSmartCamAppUi::CSmartCamAppUi():
	iSettingsData(NULL),
	iSettingsView(NULL),
	iViewFinderView(NULL),
	iCamFilter(NULL),
	iCamFilterOpen(EFalse),
	iCommFilter(NULL),
	iCommFilterOpen(EFalse),
	iViewFinderFrame(NULL),
	iLogoBmp(NULL),
	iWaitDialog(NULL),
	iStatusNav(NULL)
	{
// sordak
	m_iTotalDuration = 0;
	}

void CSmartCamAppUi::RetrieveIconFileHandleL(RFile &aFile, const TIconFileType /* aType */)
	{
	TInt err = KErrNone;
	err = aFile.Open(iFsSessionSharedProtected, iGfxFileName, EFileShareAny);
	User::LeaveIfError(err);
	}

void CSmartCamAppUi::Finished()
	{
	}

void CSmartCamAppUi::ConstructL()
	{
	// Initialise app UI with standard value.
	BaseConstructL(CAknAppUi::EAknEnableSkin);

	// Create the in memory settings data
	iSettingsData = CSmartCamSettingsData::NewL();
	// Load the settings data from the settings file
    User::LeaveIfError(iFsSessionSharedProtected.Connect());
    iFsSessionSharedProtected.ShareProtected();

    TFileName privatePath;
    User::LeaveIfError(iFsSessionSharedProtected.CreatePrivatePath(EDriveC) );
    User::LeaveIfError(iFsSessionSharedProtected.PrivatePath(privatePath));
    iSettingsFileName = privatePath;
    iSettingsFileName += KSettingsFileName;

    LoadSettings();

    // Load the Logo vector image
    iGfxFileName = privatePath;
    iGfxFileName += KGfxFileName;
    TParsePtrC parse(Application()->AppFullName());
    iGfxFileName.Insert(0, parse.Drive());

    iLogoBmp = AknIconUtils::CreateIconL(*this, EMbmSmartcamgfxLogo);
    AknIconUtils::PreserveIconData(iLogoBmp);
    AknIconUtils::SetSize(iLogoBmp, TSize(160, 120), EAspectRatioNotPreserved);

	// Create view objects
	iViewFinderView = CSmartCamViewFinderView::NewL();
	AddViewL(iViewFinderView);

	iSettingsView = CSmartCamSettingsView::NewL(*iSettingsData);
	AddViewL(iSettingsView);

	iCamFilter = CCamFilter::NewL();
	iCommFilter = CCommFilter::NewL();

	SetDefaultViewL(*iViewFinderView);
	SetStatusMsg(KDisconnected);
// sordak
	// Create the timers
	m_pTimer = CPeriodic::NewL(CActive::EPriorityIdle);
	m_pFlashTimer = CPeriodic::NewL(CActive::EPriorityIdle);
	}

void CSmartCamAppUi::LoadSettings()
	{
    RFs& fs = iEikonEnv->FsSession();
    RFileReadStream readStream;
    TInt error = readStream.Open(fs, iSettingsFileName, EFileRead);
    TInt internalizationError = KErrNone;
    // if file existed, try to read settings.
    if (error == KErrNone)
        {
        TRAP(internalizationError, iSettingsData->LoadL(readStream);)
        }
    readStream.Release();

    // reading failed, settings file might be corrupted.
    if (internalizationError != KErrNone)
        {
        User::LeaveIfError(fs.Delete(iSettingsFileName));
        }
	}

void CSmartCamAppUi::SaveSettings()
	{
    RFs& fs = iEikonEnv->FsSession();
    RFileWriteStream writeStream;
    TInt error = writeStream.Open(fs, iSettingsFileName, EFileWrite);
    // setting file did not exist, create one.
    if (error != KErrNone)
        {
        User::LeaveIfError(writeStream.Create(fs, iSettingsFileName, EFileWrite));
        }
    writeStream.PushL();
    iSettingsData->SaveL(writeStream);
    writeStream.CommitL();
    writeStream.Pop();
    writeStream.Release();
	}

CSmartCamAppUi::~CSmartCamAppUi()
	{
	Stop();

	if(iCamFilter != NULL)
		{
		delete iCamFilter;
		iCamFilter = NULL;
		}
	if(iCommFilter != NULL)
		{
		delete iCommFilter;
		iCommFilter = NULL;
		}

	if(iStatusNav != NULL)
		{
		delete iStatusNav;
		iStatusNav = NULL;
		}

	if(iLogoBmp != NULL)
		{
		delete iLogoBmp;
		iLogoBmp = NULL;
		}

	if(iSettingsData != NULL)
		{
		delete iSettingsData;
		iSettingsData = NULL;
		}
	iFsSessionSharedProtected.Close();

	iSettingsView = NULL;
	iViewFinderView = NULL;
// sordak
	if (m_pTimer)
		{
		if (m_pTimer->IsActive())
			{
			m_pTimer->Cancel();
			}
		delete m_pTimer;
		m_pTimer = NULL;
		}
	if (m_pFlashTimer)
		{
		if (m_pFlashTimer->IsActive())
			{
			m_pFlashTimer->Cancel();
			}
		delete m_pFlashTimer;
		m_pFlashTimer = NULL;
		}
	}

void CSmartCamAppUi::DynInitMenuPaneL(TInt aResourceId, CEikMenuPane* aMenuPane)
	{
	if(aResourceId == R_SMARTCAM_VIEW_FINDER_MENU)
		{
		// connected, disable the connect & settings menu items,
		// enable the disconnect menu item
		if(iCommFilterOpen)
			{
			aMenuPane->SetItemDimmed(ESmartCamCmdConnect, ETrue);
			aMenuPane->SetItemDimmed(ESmartCamCmdSettings, ETrue);
			aMenuPane->SetItemDimmed(ESmartCamCmdDisconnect, EFalse);
			}
		// not connected, enable the connect & settings menu items,
		// disable the disconnect menu item
		else
			{
			aMenuPane->SetItemDimmed(ESmartCamCmdConnect, EFalse);
			aMenuPane->SetItemDimmed(ESmartCamCmdSettings, EFalse);
			aMenuPane->SetItemDimmed(ESmartCamCmdDisconnect, ETrue);
			}
		}
	}

TKeyResponse CSmartCamAppUi::HandleKeyEventL(const TKeyEvent& /* aKeyEvent */, TEventCode /* aType */)
    {
    return EKeyWasNotConsumed;
    }

void CSmartCamAppUi::HandleSettingsChange()
	{
	SaveSettings();
	}

void CSmartCamAppUi::HandleCommandL(TInt aCommand)
	{
	switch(aCommand)
		{
		case EEikCmdExit:
		case EAknSoftkeyExit:
			Exit();
			break;
		case ESmartCamCmdConnect:
			{
			if(GetConnectionType() == EConnectionUsb)
				{
				DisplayMsgL(_L("Not yet implemented, coming soon"));
				return;
				}
			OpenPipeline();
			}
			break;
		case ESmartCamCmdDisconnect:
			{
			Stop();
			SetStatusMsg(KDisconnected);
			}
			break;
		case ESmartCamCmdSettings:
			{
			ActivateLocalViewL(KUidSettingsView);
			}
			break;
		case ESmartCamCmdHelp:
			{
            CArrayFix <TCoeHelpContext>* buf = CCoeAppUi::AppHelpContextL();
            HlpLauncher::LaunchHelpApplicationL( iEikonEnv->WsSession(), buf );
			}
			break;
		case ESmartCamCmdAbout:
			{
			CAknMessageQueryDialog* dlg = new (ELeave)CAknMessageQueryDialog();
			dlg->PrepareLC(R_ABOUT_QUERY_DIALOG);
			HBufC* title = iEikonEnv->AllocReadResourceLC(R_ABOUT_DIALOG_TITLE);
			dlg->QueryHeading()->SetTextL(*title);
			CleanupStack::PopAndDestroy(); //title
			HBufC* msg = iEikonEnv->AllocReadResourceLC(R_ABOUT_DIALOG_TEXT);
			dlg->SetMessageTextL(*msg);
			CleanupStack::PopAndDestroy(); //msg
			dlg->RunLD();
			}
			break;
		default:
			Panic(ESmartCamUi);
			break;
		}
	}

void CSmartCamAppUi::HandleResourceChangeL(TInt aType)
    {
    // base-class call also
    CAknViewAppUi::HandleResourceChangeL(aType);

    if(aType == KEikDynamicLayoutVariantSwitch)
        {
        iViewFinderView->HandleSizeChange();
        iSettingsView->HandleSizeChange();
        }
    }

void CSmartCamAppUi::DisplayFrame(CFbsBitmap* aFrame)
	{
	iViewFinderFrame = aFrame;
	iViewFinderView->ForceRedraw();
	iViewFinderFrame = NULL;
	}

CFbsBitmap* CSmartCamAppUi::ViewFinderFrame()
	{
	return iViewFinderFrame;
	}

CFbsBitmap* CSmartCamAppUi::LogoBmp()
	{
	return iLogoBmp;
	}

TDes& CSmartCamAppUi::GetInetServer()
	{
	return iSettingsData->InetServer();
	}

TInt CSmartCamAppUi::GetInetPort()
	{
	return iSettingsData->InetPort();
	}

TDes& CSmartCamAppUi::GetBtServerAddr()
	{
	return iSettingsData->BtServerAddr();
	}

TConnType CSmartCamAppUi::GetConnectionType()
	{
	return (TConnType) (iSettingsData->ConnectionType());
	}

TBool CSmartCamAppUi::IsConnected()
	{
	return iCommFilterOpen;
	}

void CSmartCamAppUi::OpenPipeline()
	{
	iCamFilter->Open(this);
	iCommFilter->Open(this);
	iWaitDialog = new (ELeave) CAknWaitDialog((REINTERPRET_CAST(CEikDialog**, &iWaitDialog)));
	iWaitDialog->ExecuteLD(R_CONNECTING_NOTE);
	}

void CSmartCamAppUi::Start()
	{
	iCamFilter->Start();
	}

void CSmartCamAppUi::Stop()
	{
	if(iCamFilterOpen)
		{
		iCamFilter->Close();
		iCamFilterOpen = EFalse;
		}
	if(iCommFilterOpen)
		{
		iCommFilter->Close();
		iCommFilterOpen = EFalse;
		}
	}

void CSmartCamAppUi::OpenComplete(MStreamFilter* aFilter, TInt aError, const TDesC& aErrMsg)
	{
	if(aFilter == iCommFilter)
		iWaitDialog->ProcessFinishedL();

	if(aError == KErrNone)
		{
		if(aFilter == iCamFilter)
			{
			iCamFilterOpen = ETrue;
			}
		else if(aFilter == iCommFilter)
			{
			iCommFilterOpen = ETrue;
			SetStatusMsg(KConnected);
			}
		// If all the filter were successfully opened, start the pipeline
		if(iCamFilterOpen && iCommFilterOpen)
			{
			iCamFilter->AttachCommFilter(iCommFilter);
			Start();
// sordak
			if (IsRunning()){StopTimer();ResetTimer();SetDuration(5);}
			}
		}
	else // Error
		{
		_LIT(KilyasrkError,"Error");
//		SetStatusMsg(KDisconnected);
		SetStatusMsg(KilyasrkError);
		Stop();
//		if(aErrMsg != KNullDesC)
//			{
//			DisplayMsgL(aErrMsg);
//			}
		if (IsRunning()){StopTimer();}
		SetDuration(30);
		ResetTimer();
		StartTimer();
		}
	}

void CSmartCamAppUi::OnFilterError(MStreamFilter* /* aFilter */, TInt /* aError */, const TDesC& aErrMsg)
	{
_LIT(KilyasrkOnFilterError,"OnFilterError");
//	SetStatusMsg(KDisconnected);
	SetStatusMsg(KilyasrkOnFilterError);
	Stop();
//	if(aErrMsg != KNullDesC)
//		{
//		DisplayMsgL(aErrMsg);
//		}
// sordak
	if (IsRunning()){StopTimer();}
	SetDuration(5);
	ResetTimer();
	StartTimer();
	}

void CSmartCamAppUi::EnumerateVideoResolutions(TInt aCameraIndex, RArray<TSize>& aArray)
	{
	iCamFilter->EnumerateVideoResolutions(aCameraIndex, aArray);
	}

void CSmartCamAppUi::EnumerateVideoFrameRates(TInt aCameraIndex, TInt aResolutionIndex, RArray<TReal32>& aArray)
	{
	iCamFilter->EnumerateVideoFrameRates(aCameraIndex, aResolutionIndex, aArray);
	}

void CSmartCamAppUi::DisplayMsgL(const TDesC& aMsg)
	{
	CAknQueryDialog* errDlg = CAknQueryDialog::NewL(CAknQueryDialog::ENoTone);
	errDlg->SetPromptL(aMsg);
	errDlg->ExecuteLD(R_ERR_MSG);
	}

void CSmartCamAppUi::SetStatusMsg(const TDesC& aMsg)
	{
	CEikStatusPane *sp = StatusPane();
	CAknNavigationControlContainer *np =
		(CAknNavigationControlContainer *)sp->ControlL(TUid::Uid(EEikStatusPaneUidNavi));
	if(iStatusNav != NULL)
		{
		np->Pop(iStatusNav);
		delete iStatusNav;
		iStatusNav = NULL;
		}
	iStatusNav = np->CreateNavigationLabelL(aMsg);
	np->PushL(*iStatusNav);
	}

TInt CSmartCamAppUi::GetDuration()
{
  return m_iTotalDuration;
}

void CSmartCamAppUi::SetDuration(TInt n_iDuration)
{
  if (!IsRunning())
  {
    m_iTotalDuration = n_iDuration;
    m_iRemainingDuration = m_iTotalDuration;
  }
}

TBool CSmartCamAppUi::IsRunning()
{
  if (m_pTimer && m_pTimer->IsActive())
  {
    return ETrue;
  }
  return EFalse;
}

TBool CSmartCamAppUi::IsReset()
{
  if (m_pTimer && !m_pTimer->IsActive() && m_iTotalDuration == m_iRemainingDuration)
  {
    return ETrue;
  }
  return EFalse;
}

TInt CSmartCamAppUi::TimerFired(TAny* aPtr)
{
  CSmartCamAppUi* pThis((CSmartCamAppUi*)aPtr);
  if (pThis)
  {
    pThis->DoTimerFired();
  }
  return TRUE;
}

void CSmartCamAppUi::DoTimerFired()
{
  --m_iRemainingDuration;
  if (m_iRemainingDuration == 0)
	  {
	  OpenPipeline();
	  }
}

TBool CSmartCamAppUi::StartTimer()
{
  if (m_pFlashTimer && m_pFlashTimer->IsActive())
  {
    m_pFlashTimer->Cancel();
  }
  if (m_pTimer && !m_pTimer->IsActive())
  {
    m_pTimer->Start(ONE_SECOND, ONE_SECOND, TCallBack(CSmartCamAppUi::TimerFired, this));
    return ETrue;
  }
  return EFalse;
}

TBool CSmartCamAppUi::StopTimer()
{
  if (m_pFlashTimer && m_pFlashTimer->IsActive())
  {
    m_pFlashTimer->Cancel();
  }
  if (m_pTimer && m_pTimer->IsActive())
  {
    m_pTimer->Cancel();
  }
  return ETrue;
}

TBool CSmartCamAppUi::ResetTimer()
{
  if (m_pFlashTimer && m_pFlashTimer->IsActive())
  {
    m_pFlashTimer->Cancel();
  }
  if (m_pTimer && m_pTimer->IsActive())
  {
    m_pTimer->Cancel();
  }

  m_iRemainingDuration = m_iTotalDuration;

  return ETrue;
}

TInt CSmartCamAppUi::FlashTimerFired(TAny* aPtr)
{
CSmartCamAppUi* pThis((CSmartCamAppUi*)aPtr);
  if (pThis)
  {
    pThis->DoFlashTimerFired();
  }
  return TRUE;
}

void CSmartCamAppUi::DoFlashTimerFired()
{
  m_bFlash = !m_bFlash;
}

CArrayFix <TCoeHelpContext>* CSmartCamAppUi::HelpContextL() const
    {
    CArrayFixFlat <TCoeHelpContext>* array =
                new ( ELeave )CArrayFixFlat <TCoeHelpContext> ( 1 );
    CleanupStack::PushL( array );
    array->AppendL(TCoeHelpContext(KUidSmartCamApp, KGeneral_Information));//KContextApplication));
    CleanupStack::Pop( array );
    return array;
    }
